using Sustainalytics.Synchronization.Validation.Internals;
using Sustainalytics.Synchronization.Validation.ValidationRules.Common;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sustainalytics.Synchronization.Validation.Validators
{
    public class Validator<T>
    {
        protected readonly ICollection<Rule<T>> ValidationRules = new List<Rule<T>>();

        public Validator(IEnumerable<Rule<T>> rules)
        {
            foreach (var rule in rules)
            {
                ValidationRules.Add(rule);
            }
        }

        public bool HasAssignedRules => this.ValidationRules.Any();

        protected ValidationResult ValidationResult { get; set; }

        public Validator<T> AddRule(Rule<T> validationRule)
        {
            ValidationRules.Add(validationRule);
            return this;
        }

        public virtual Task<ValidationResult> ValidateAsync(T validatedObject, T referenceObject)
        {
            ValidationResult = new ValidationResult();

            if (validatedObject.Equals(default(T)))
            {
                throw new ValidationException("Invalid object");
            }

            foreach (var validationRule in ValidationRules)
            {
                if (!validationRule.IsValid(validatedObject, referenceObject))
                {
                    ValidationResult.AddError(
                       validationRule.GetKey(validatedObject),
                       validationRule.GetErrorMessage(),
                       validationRule.Severity,
                       validationRule.BusinessResearchProduct,
                       validationRule.Code,
                       validationRule.InformationalMessage,
                       validationRule.Triggers);
                }
            }

            return Task.FromResult(ValidationResult);
        }
    }
}
